package com.dtec.common.util;

import gov.nist.applet.phone.ua.gui.ServerInfoXmlManager;

import java.io.File;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;

import org.apache.commons.lang.ArrayUtils;

import jmapps.registry.SettingsPanel;

import com.dtec.resource.settingInfo.Account;
import com.dtec.resource.settingInfo.AdvanceSettings;
import com.dtec.resource.settingInfo.Contact;
import com.dtec.resource.settingInfo.History;

public class SettingUtil {
	static final public int OPERATION_ADD = 1;
	static final public int OPERATION_DELETE = 2;
	static final public int OPERATION_EDIT = 3;
	static final public int OPERATION_FIND = 4;
	static ServerInfoXmlManager xmlManager = null;
	final static public String acccountPath = "xmlSource/ServerInfo.xml";
	final static public String advanceSettingsPath = "xmlSource/AdvanceSettings.xml";
	final static public String HistoryPath = "xmlSource/History.xml";
	final static public String ContactPath = "xmlSource/Contact.xml";

	public static Object SaveSetting(Object target, int Operation) {
		return SaveSetting(target, acccountPath, Operation);
	}

	public static Object SaveSetting(Object target, URL path, int Operation) {
		return SaveSetting(target, path.getPath(), Operation);
	}

	public static Object SaveSetting(Object target, String path, int Operation) {
		xmlManager = new ServerInfoXmlManager(path);
		Object o = new Object();
		switch (Operation) {
		case OPERATION_ADD:
			o = add(target);
			break;
		case OPERATION_DELETE:
			o = delete(target);
			break;
		case OPERATION_EDIT:
			o = edit(target);
			break;
		case OPERATION_FIND:
			o = find(target);
			break;

		default:
			break;
		}

		return o;
	}

	private static String add(Object object) {
		ArrayList al = new ArrayList();
		if (object instanceof java.util.ArrayList) {
			al = (ArrayList) object;
		} else if (object instanceof String) {
			return (String) object;
		} else {
			al.add(object);
		}
		StringBuffer str = new StringBuffer("");
		for (Object obj : al) {
			String cn = getShortClassName(obj.getClass().getName())
					.toLowerCase();
			str.append("<" + cn + ">");
			Method[] methods = obj.getClass().getMethods();
			for (Method method : methods) {
				if (method.getName().startsWith("get")) {
					String Name = method.getName().substring(3).toLowerCase();
					if (String.class.equals(method.getReturnType())) {
						str.append("<info value=\"" + Name + "\">");
						try {
							str.append((String) method.invoke(obj,
									new Object[] {}));
						} catch (Exception e) {
							e.printStackTrace();
						}
						str.append("</info>");
					}
				}
			}
			str.append("</" + cn + ">");
		}
		return str.toString();
	}

	private static String delete(Object target) {
		String str = "";
		try {
			Method getId = target.getClass().getMethod("getId", null);
			String val = (String) getId.invoke(target, new Object[] {});
			ArrayList al = find(target);
			for (Object object : al) {
				Method objgetId = object.getClass().getMethod("getId", null);
				String objval = (String) objgetId.invoke(object,
						new Object[] {});
				if (val.equals(objval)) {
					al.remove(object);
				}
				str = add(al);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return str;
	}

	private static String edit(Object target) {
		ArrayList al = find(target);
		try {
			Method m = target.getClass().getMethod("getId", null);
			String tVal = (String) m.invoke(target, new Object[] {});
			for (Object obj : al) {
				Method method = obj.getClass().getMethod("getId", null);
				String objVal = (String) method.invoke(obj, new Object[] {});
				if (objVal.equals(tVal)) {
					al.set(al.indexOf(obj), target);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return add(al);
	}

	private static ArrayList find(Object obj) {
		ArrayList r = new ArrayList();
		ArrayList query = xmlManager.readXmlExtended();
		for (Object o : query) {
			Object ri = null;
			try {
				ri = obj.getClass().newInstance();
				// ri = (obj.getClass().getConstructor()).newInstance();
			} catch (Exception e) {
				e.printStackTrace();
			}
			Method[] methods = ri.getClass().getMethods();
			for (Method method : methods) {
				if (method.getName().startsWith("set")) {
					String Name = method.getName().substring(3).toLowerCase();
					if (String.class.equals(method.getParameterTypes()[0])) {
						Map map = (Map) o;
						Iterator it = map.entrySet().iterator();
						while (it.hasNext()) {
							Map.Entry entry = (Entry) it.next();
							Object key = entry.getKey();
							Object value = entry.getValue();
							if (key.toString().equals(Name)) {
								try {
									method.invoke(ri,
											new Object[] { (String) value });
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
			}
			r.add(ri);
		}
		return r;
	}

	/**
	 * @param path
	 *            为null时，path将默认设定为accountPath
	 * @param r
	 *            编辑好了的String形式xml节点
	 */
	public static void createXML(String path, String r) {
		xmlManager.writerXML(path == null ? acccountPath : path, r);
	}

	/*************************** Account *****************************/

	public static void addAccount(Account account, String path) {
		ArrayList<Account> as = (ArrayList<Account>) SettingUtil.SaveSetting(
				account, path, SettingUtil.OPERATION_FIND);
		String acc1 = account.getName() + "@" + account.getProxyaddress() + ":"
				+ account.getProxyport();
		for (Account a : as) {
			String acc2 = a.getName() + "@" + a.getProxyaddress() + ":"
					+ a.getProxyport();
			if (acc1.equals(acc2)) {
				return;
			}
		}
		if (account.getDefaulAccount().equals("1")) {
			for (Account a : as) {
				if (a.getDefaulAccount().equals("1")) {
					a.setDefaulAccount("0");
				}
			}
		}
		as.add(account);
		String str = (String) SettingUtil.SaveSetting(as,
				SettingUtil.OPERATION_ADD);
		SettingUtil.createXML(path, str);
	}

	public static void delAccount(String id, String path) {
		ArrayList<Account> as = (ArrayList<Account>) SettingUtil.SaveSetting(
				new Account(), path, SettingUtil.OPERATION_FIND);
		int index = -1;
		for (Account a : as) {
			if (a.getId().equals(id)) {
				index = as.indexOf(a);
				break;
			}
		}
		as.remove(index);
		String str = (String) SettingUtil.SaveSetting(as,
				SettingUtil.OPERATION_ADD);
		SettingUtil.createXML(path, str);
	}

	public static void editAccout(Account account, String path) {
		ArrayList<Account> as = (ArrayList<Account>) SettingUtil.SaveSetting(
				account, path, SettingUtil.OPERATION_FIND);
		String id = account.getId();
		for (Account a : as) {
			if (a.getId().equals(id)) {
				as.set(as.indexOf(a), account);
			}
		}

		if (account.getDefaulAccount().equals("1")) {
			for (Account a : as) {
				if (a.getDefaulAccount().equals("1") && a != account) {
					a.setDefaulAccount("0");
				}
			}
		}

		String str = (String) SettingUtil.SaveSetting(as,
				SettingUtil.OPERATION_ADD);
		SettingUtil.createXML(path, str);

	}

	public static Account getDefaultAccount(String path) {
		Account account = new Account();
		@SuppressWarnings("unchecked")
		ArrayList<Account> as = (ArrayList<Account>) SettingUtil.SaveSetting(
				account, path, SettingUtil.OPERATION_FIND);
		for (Account a : as) {
			if (a.getDefaulAccount().equals("1")) {
				return a;
			}
		}
		return null;
	}

	public static Account getDefaultAccount() {
		return getDefaultAccount(SettingUtil.acccountPath);
	}

	@SuppressWarnings("unchecked")
	public static ArrayList<Account> getAccounts() {
		return (ArrayList<Account>) SettingUtil.SaveSetting(new Account(),
				SettingUtil.OPERATION_FIND);
	}

	/************************** AdvanceSetting ******************************/

	public static void setAdvanceSettings(AdvanceSettings as, String path) {
		path = path == null ? advanceSettingsPath : path;
		String str = (String) SaveSetting(as, path, OPERATION_ADD);
		createXML(path, str);
	}

	public static AdvanceSettings getAdvanceSettings(String path) {
		@SuppressWarnings("unchecked")
		ArrayList<AdvanceSettings> as = (ArrayList<AdvanceSettings>) SettingUtil
				.SaveSetting(new AdvanceSettings(), path,
						SettingUtil.OPERATION_FIND);
		return as.get(0);
	}

	/************************** History ******************************/
	public static void addHistory(History h, String path) {
		path = path == null ? HistoryPath : path;
		ArrayList<History> hs = (ArrayList<History>) SettingUtil.SaveSetting(
				new History(), path, SettingUtil.OPERATION_FIND);
		for (History history : hs) {
			if(history.getDialDate().equals(h.getDialDate())){
				return;
			}
		}
		if(hs.size()>=50){
			hs.remove(49);
		}
		hs.add(0, h);
		String str = (String) SaveSetting(hs, path, OPERATION_ADD);
		createXML(path, str);
	}

	public static ArrayList<History> getHistory(String query, String path) {
		path = path == null ? HistoryPath : path;
		@SuppressWarnings("unchecked")
		ArrayList<History> hs = (ArrayList<History>) SettingUtil.SaveSetting(
				new History(), path, SettingUtil.OPERATION_FIND);
		if(query==null || "".equals(query)){
			return hs;
		}
		ArrayList<History> hss = new ArrayList<History>();
		for (History history : hs) {
			if (history.getContactAddress().contains(query)) {
				hss.add(history);
			}
		}
		return hss;
	}

	public static void clearHistory(String path) {
		path = path == null ? HistoryPath : path;
		xmlManager = new ServerInfoXmlManager(path);
		createXML(path, "");
	}

	/************************** Contact ******************************/
	public static void addContact(Contact c, String path) {
		path = path == null ? ContactPath : path;
		ArrayList<Contact> cs = (ArrayList<Contact>) SettingUtil.SaveSetting(
				new Contact(), path, SettingUtil.OPERATION_FIND);
		for (Contact contact : cs) {
			if(contact.getContactAddress().trim().equals(c.getContactAddress().trim())){
				return;
			}
		}
		cs.add(c);
		String str = (String) SaveSetting(cs, path, OPERATION_ADD);
		createXML(path, str);
	}

	public static ArrayList<Contact> getContacts(String query, String path) {
		path = path == null ? ContactPath : path;
		@SuppressWarnings("unchecked")
		ArrayList<Contact> cs = (ArrayList<Contact>) SettingUtil.SaveSetting(
				new Contact(), path, SettingUtil.OPERATION_FIND);
		if(query==null || "".equals(query)){
			return cs;
		}
		ArrayList<Contact> css = new ArrayList<Contact>();
		for (Contact contact : cs) {
			if (contact.getContactAddress().contains(query)) {
				css.add(contact);
			}
		}
		return css;
	}

	public static void deleteContact(Contact c, String path) {
		path = path == null ? ContactPath : path;
		@SuppressWarnings("unchecked")
		ArrayList<Contact> cs = (ArrayList<Contact>) SettingUtil.SaveSetting(
				new Contact(), path, SettingUtil.OPERATION_FIND);
		int index=-1;
		for (Contact contact : cs) {
			if(contact.getId().equals(c.getId())){
				index=cs.indexOf(contact);
				break;
			}
		}
		if(index!=-1){
			cs.remove(index);
		}
		String str=(String) SaveSetting(cs, path, OPERATION_ADD);
		createXML(path, str);
	}

	public static String getShortClassName(String str) {
		StringTokenizer st = new StringTokenizer(str, ".");
		String result = "";
		while (st.hasMoreTokens()) {
			result = st.nextToken();
		}
		return result;
	}

	public static void main(String[] args) {
//		Contact c=new Contact();
//		c.setContactAddress("100@172.16.200.187");
//		c.setName("daisy");
//		SettingUtil.addContact(c, SettingUtil.ContactPath);
//		ArrayList<Contact> cs=SettingUtil.getContacts(null, null);
//		for (Contact contact : cs) {
//			System.out.println(contact.getId());
//		}
//		SettingUtil.deleteContact(cs.get(0), null);
//		System.out.println("-----------------------");
//		cs=SettingUtil.getContacts(null, null);
//		for (Contact contact : cs) {
//			System.out.println(contact.getId());
//		}
		SettingUtil.clearHistory(null);
	}

}
